/*
 * Flashlib - QB9 common Flash library
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package com.qb9.flashlib.color
{
	/**
	 * Represents a given color, and allows to convert between its hex and rgb representations.
	 */
	public class Color
	{
		public static const BLACK	: uint = 0x000000;
		public static const WHITE	: uint = 0xFFFFFF;
		public static const RED		: uint = 0xFF0000;
		public static const ORANGE	: uint = 0xFF6600;
		public static const GREEN	: uint = 0x00FF00;
		public static const PURPLE	: uint = 0x9000BB;
		public static const PINK	: uint = 0xFF00FC;
		public static const BLUE	: uint = 0x0000FF;
		public static const CYAN	: uint = 0x28C9E6;
		public static const YELLOW	: uint = 0xFFFF00;		
		
		protected var _hex:uint;
		protected var _brightness:Number;
		
		public function Color(hex:uint)
		{
			_hex = hex;
			_brightness = 1;
		}
		
		/**
		 * Creates a new color instance based on its r, g and b values.
		 * @param r The red value of the color.
		 * @param g The green value of the color.
		 * @param b The blue value of the color.
		 * @return A new color instance.
		 */ 
		public static function fromRGB(r:uint, g:uint, b:uint) : Color
		{
			return new Color(rgbToHex(r,g,b));
		}
		
		/**
		 * Converts a set of r-g-b values to their hexadecimal version
		 * @param r The red value of the color.
		 * @param g The green value of the color.
		 * @param b The blue value of the color.
		 * @return The hexadecimal number
		 */ 
		public static function rgbToHex(r:uint, g:uint, b:uint) : uint
		{
			return (
				(limit(r) << 16) |
				(limit(g) <<  8) |
				(limit(b) <<  0)
			);
		}
		
		public static function interpolate(color1:Color, color2:Color, progress:Number):Color
		{
			var q:Number = 1 - progress;
			return fromRGB(
				color1.r * q + color2.r * progress,
				color1.g * q + color2.g * progress,
				color1.b * q + color2.b * progress
			);
		}
		
		public static function interpolateHex(color1:uint, color2:uint, progress:Number):uint
		{
			return interpolate(new Color(color1), new Color(color2), progress).hex; 
		}
		
		/**
		 * @return The brightness of the color [0,1].
		 */
		public function get brightness() : Number
		{
			return _brightness;
		}
		
		/**
		 * @private
		 */
		public function set brightness(b:Number) : void
		{
			_brightness = b;
		}
		
		/**
		 * @return The hexadecimal value of the color
		 */
		public function get hex() : uint
		{
			return limit(_hex * _brightness, 0xFFFFFF);
		}
		
		/* RGB */
		
		/**
		 * @return The red part of the color
		 */
		public function get r() : uint
		{
			return slice(2);
		}
		
		/**
		 * @return The green part of the color
		 */
		public function get g() : uint
		{
			return slice(1);
		}
		
		/**
		 * @return The blue part of the color
		 */
		public function get b() : uint
		{
			return slice(0);
		}
		
		protected function slice(index:uint) : uint
		{
			return limit(
				((_hex >> index * 8) & 0xFF) * _brightness
			);
		}
		
		/* Operations on other Colors */
		
		/**
		 * Sums another color object to the present one.
		 * @param color The color to sum
		 * @return A new Color instance
		 */
		public function add(color:Color) : Color
		{
			return Color.fromRGB(
				this.r + color.r,
				this.g + color.g,
				this.b + color.b
			);
		}
		
		/**
		 * Substracts another color object from the present one.
		 * @param color The color to substract
		 * @return A new Color instance
		 */
		public function sub(color:Color) : Color
		{
			return Color.fromRGB(
				this.r - color.r,
				this.g - color.g,
				this.b - color.b
			);
		}
		
		protected static function limit(num:int, max:uint = 0xFF) : uint
		{
			return num <= 0   ? 0 :
				   num >= max ? max :
				   num;
		}

		public function equals(color:Color):Boolean
		{
			return hex === color.hex;
		}
	}
}
